#include "gtest/gtest.h"
#include "../BaseUtil/MyTest.h"
#include "DOMCoreImp.h"
namespace DOMCoreImp {

class ElementImpTest : public testing::Test {
protected:
	virtual void SetUp() {
		doc = new DocumentImp();
		elem = doc->createElementImp( "myElement" );
	}
	virtual void TearDown() {
		delete doc;
	}

	DocumentImp * doc;
	ElementImp * elem;
};

TEST_F(ElementImpTest, Inheritance) {
	ElementImpPtr( new ElementImp( "Casting1", NULL ) );
	NodeImpPtr( new ElementImp( "Casting2", NULL ) );
	ElementPtr( new ElementImp( "Casting2", NULL ) );
}

TEST_F(ElementImpTest, NodeType) {
	ASSERT_EQ( Node::ELEMENT_NODE, elem->getNodeType() );
}

TEST_F(ElementImpTest, TagName) {
	ASSERT_STREQ( "myElement", elem->getTagName().c_str() );
	ASSERT_STREQ( "myElement", elem->getNodeName().c_str() );
}

TEST_F(ElementImpTest, Value) {
	ASSERT_TRUE( elem->getNodeValue().empty() );
	ASSERT_THROW( elem->setNodeValue("aa"), DOMExceptionPtr );
}

TEST_F(ElementImpTest, SetAttributeByValue) {
	ASSERT_TRUE( elem->getOwnerDocument() );
	elem->setAttribute( "Jay", "A man" );
	NamedAttrMap * attrMap = elem->getAttributes();
	ASSERT_TRUE( attrMap );
	Attr * attr = attrMap->getNamedItem( "Jay" );
	ASSERT_TRUE( attr );
	ASSERT_STREQ( "A man", attr->getValue().c_str() );
}

TEST_F(ElementImpTest, Attribute) {
	ASSERT_TRUE( elem->getAttributes() );
	ASSERT_TRUE( false == elem->hasAttributes() );

	ASSERT_TRUE( elem->getAttributes() );
	elem->setAttribute( "Jay", "A man" );
	ASSERT_TRUE( true == elem->hasAttributes() );
}

TEST_F(ElementImpTest, HasAttributeByName) {
	elem->setAttribute( "Jay", "A man" );
	ASSERT_TRUE( elem->hasAttribute( "Jay" ) );
	ASSERT_FALSE( elem->hasAttribute( "jay" ) );
}

TEST_F(ElementImpTest, GetAttributeByNode) {
	ASSERT_FALSE( elem->getAttributeNode( "jay" ) );
	elem->setAttribute( "Jay", "A man" );
	ASSERT_FALSE( elem->getAttributeNode( "jay" ) );
	Attr * node = elem->getAttributeNode( "Jay" );
	ASSERT_TRUE( node );
	ASSERT_STREQ( "A man", node->getValue().c_str() );
}

TEST_F(ElementImpTest, SetAttributeByNode) {
	Attr * newAttr = doc->createAttribute("newAttr");
	ASSERT_TRUE( newAttr );
	DOMString name = newAttr->getName();
	ASSERT_STREQ( "newAttr", name.c_str() );
	ASSERT_FALSE( elem->setAttributeNode( newAttr ) );
	ASSERT_EQ( newAttr, elem->getAttributeNode( "newAttr" ) );
}

TEST_F(ElementImpTest, SetAttributeByNodeReturnsReplacedNode) {
	Attr * newAttr1 = doc->createAttribute("sameName");
	Attr * newAttr2 = doc->createAttribute("sameName");
	ASSERT_FALSE( elem->setAttributeNode( newAttr1 ) );
	ASSERT_EQ( newAttr1, elem->setAttributeNode( newAttr2 ) );

	ASSERT_EQ( newAttr2, elem->getAttributeNode( "sameName" ) );
}

TEST_F(ElementImpTest, SetAttributeByNodeThrowException) {
	ElementImp * anotherElement = doc->createElementImp("anotherElement");
	ASSERT_TRUE( anotherElement );
	anotherElement->setAttribute( "othersAttr", "Jay" );
	Attr * othersAttr = anotherElement->getAttributeNode( "othersAttr" );
	ASSERT_TRUE( othersAttr );
	ASSERT_EQ( anotherElement, othersAttr->getParentNode() );

	ASSERT_THROW( elem->setAttributeNode( othersAttr ), DOMExceptionPtr );
}

TEST_F(ElementImpTest, SetAttributeByNodeThrowExceptionForWrongDocument) {
	DocumentImp * alienDoc = new DocumentImp();
	Attr * alienAttr = alienDoc->createAttribute( "othersAttr" );
	ASSERT_TRUE( alienAttr );
	ASSERT_EQ( alienDoc, alienAttr->getOwnerDocument() );

	ASSERT_THROW( elem->setAttributeNode( alienAttr ), DOMExceptionPtr );
}

TEST_F(ElementImpTest, RemoveAttributeByName) {
	elem->setAttribute( "Jay", "A man" );
	ASSERT_TRUE( elem->getAttributeNode( "Jay" ) );
	elem->removeAttribute( "Jay" );
	ASSERT_FALSE( elem->getAttributeNode( "Jay" ) );
}

TEST_F(ElementImpTest, RemoveAttributeByNode) {
	Attr * newAttr = doc->createAttribute("newAttr");
	elem->setAttributeNode( newAttr );
	ASSERT_EQ( newAttr, elem->getAttributeNode( "newAttr") );
	ASSERT_EQ( newAttr, elem->removeAttributeNode( newAttr ) );
	ASSERT_FALSE( elem->getAttributeNode( "newAttr") );
}

TEST_F(ElementImpTest, ListElementsByTagName) {
	// TODO
//NodeList * getElementsByTagName(DOMString name);
}

}
